home *** CD-ROM | disk | FTP | other *** search
- /*
- Commodore 64 Emulator v0.1 Earle F. Philhower III
- Copyright (C) 1993-4 (st916w9r@dunx1.ocs.drexel.edu)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include "Memory.h"
- #include "MemoryCalls.h"
- #include "Error.h"
- #include "QDOffscreen.h"
- #include <GestaltEqu.h>
-
- void TotalRedrawVIC(void);
- void SetupColorTable(void);
- OSErr CreateGDevice (PixMapHandle, GDHandle*);
- void NewBitMap (PixMapHandle, Rect*);
- OSErr CreateOffScreen (Rect*, short, CTabHandle, CGrafPtr*, GDHandle*);
- OSErr SetUpPixMap(short, Rect*, CTabHandle, short, PixMapHandle);
- Boolean isPressed (unsigned short);
-
- /*
- kPixDepth is the pixel depth of the offscreen pixmap,
- kClutID is the resID of the color table,
- and kDefaultRes has to do with the screen resolution of the GDevice
- */
-
- #define kPixDepth 8
- #define kClutID 1001
- #define kDefaultRes 0x00480000
-
- #define FastDraw(row,col,chr)\
- { tempa=(row<<3) + screenRect.top; tempb=chr<<3;\
- Index2Color (RAM[55296 + chr], &frontCol);\
- RGBForeColor (&frontCol);\
- for (line=0;line<8;line++)\
- for (h=(col<<3)+screenRect.left,pos=0x80;pos>0;pos>>=1,++h)\
- if (*(VICCharDefs+tempb+line)&pos) {\
- MoveTo(h,line+tempa);\
- Line(0,0);}\
- }
-
- /*
- *(lineStart[tempa+line]+h) = RAM[55296+chr];\
- currently, everything uses FastDraw. I had FullDraw in there because the cursor
- wasn't flashing when the FastDraw macro was slower than it is now.
- */
-
- #define FullDraw(row,col,chr)\
- { tempa=(row<<3) + screenRect.top; tempb=chr<<3;\
- Index2Color (RAM[55296 + chr], &frontCol);\
- for (line=0;line<8;line++)\
- for (h=(col<<3) + screenRect.left,pos=0x80;pos>0;pos>>=1,++h)\
- if (*(VICCharDefs+tempb+line)&pos) {\
- RGBForeColor (&frontCol);\
- MoveTo(h,line+tempa);\
- Line(0,0);}\
- else {\
- RGBForeColor (&backCol);\
- MoveTo(h,line+tempa);\
- Line(0,0);}\
- }
-
- CWindowPtr VICWind;
- byte VICText[1024], VICColor[1024], VICRegister[0x2f];
- word VICAddrBase, VICScreenPage, VICCharBase;
- byte VICBank, *VICCharDefs;
- byte *lineStart[200];
-
- Rect fullRect, leftRect, rightRect, topRect, botRect, spr, screenRect;
- PixMapHandle spriteMapH;
- CTabHandle VICTab;
- GDHandle offDev;
- RGBColor VICcolors[16];
- CGrafPtr offScreenPtr;
- CGrafPtr spriteGraf; /* not used yet */
-
-
- int VICInitialize()
- {
- int row;
- short err;
- short i;
- CTabHandle vicColors;
-
- SetRect(&fullRect,0,0,336,210);
- SetRect(&screenRect,8,5,328,205);
- SetRect(&leftRect,0,0,8,210);
- SetRect(&rightRect,328,0,336,210);
- SetRect(&topRect,0,0,336,5);
- SetRect(&botRect,0,205,336,210);
- SetRect(&spr,0,0,24,21);
- SetupColorTable();
- VICWind = (CWindowPtr)GetNewCWindow (128, nil, (WindowPtr)-1L);
- if (VICWind==nil) return (kWindowMissing);
- vicColors = VICTab;
- err = HandToHand((Handle*)&vicColors);
- (**(VICWind->portPixMap)).pixelType = 0;
- (**(VICWind->portPixMap)).cmpCount = 1;
- (**(VICWind->portPixMap)).cmpSize = kPixDepth;
- (**(VICWind->portPixMap)).pmTable = vicColors;
- DisposCTable(vicColors);
- ShowWindow((WindowPtr)VICWind);
- SetPort((GrafPtr)VICWind);
- SelectWindow((WindowPtr)VICWind);
- spriteMapH = NewPixMap();
- SetUpPixMap(kPixDepth, &spr, VICTab, kPixDepth*(spr.right-spr.left), spriteMapH);
- CreateOffScreen (&fullRect, kPixDepth, VICTab, &offScreenPtr, &offDev);
- for (row=0; row<200; row++)
- lineStart[row]=(byte*)((**(offScreenPtr->portPixMap)).baseAddr)+((**(offScreenPtr->portPixMap)).rowBytes - 0x8000)*row;
- return(kNoError);
- }
-
- void VICAddrAdjust()
- {
- VICBank=(RAM[0xdd00]&3)^3;
- VICAddrBase=VICBank*16384;
- VICScreenPage=((RAM[0xd018]&0xf0)>>4)*0x0400+VICAddrBase;
- VICCharBase=((RAM[0xd018]&0x0e)*1024);
- if ((VICBank==1)||(VICBank==3))
- VICCharDefs=RAM+(VICAddrBase+VICCharBase);
- else
- if (VICCharBase==4096) VICCharDefs=charROM;
- else if (VICCharBase==6144) VICCharDefs=charROM+0x0800;
- else VICCharDefs=RAM+(VICAddrBase+VICCharBase);
- }
-
- byte NotSameVIC()
- {
- register byte addr;
-
- for (addr=0; addr<0x2f; addr++) {
- if (addr==0x11)
- { if ((RAM[0xd011]&127)!=(VICRegister[0x11]&127))
- return 1;}
- else if (addr==0x12);
- else if (RAM[0xd000+addr]!=VICRegister[addr]) return 1; }
- return 0;
- }
-
- void DrawSprites()
- {
- byte spriteNum, row, *spb0, *spb1, *spb2;
- word xpos, ypos, addr0, addr1, addr2;
- Rect t;
- GrafPtr savePort;
- GDHandle gdh;
-
- /* BlockMove((**VICMapH).baseAddr, (**fullMapH).baseAddr,
- GetPtrSize((**VICMapH).baseAddr));
- */
- SetPortPix (spriteMapH);
- for (spriteNum=0; spriteNum<8; spriteNum++)
- if (VICRegister[0x15]&(1<<spriteNum)) {
- xpos=VICRegister[0x00+spriteNum*2]-24;
- ypos=VICRegister[0x01+spriteNum*2]-50;
- xpos += (VICRegister[0x10]&(1<<spriteNum))?256:0;
- t.top=ypos;t.left=xpos;
- t.right=t.left+24+((VICRegister[0x1d]&(1<<spriteNum))?24:0);
- t.bottom=t.top+21+((VICRegister[0x17]&(1<<spriteNum))?21:0);
- addr0 = VICAddrBase+RAM[VICScreenPage+1016+spriteNum]*64;
- addr1 = addr0+1;
- addr2 = addr1+1;
- spb0 = (byte*) ((**spriteMapH).baseAddr);
- spb1 = spb0+1;
- spb2 = spb0+2;
- for (row=0; row<21; row++) {
- spb0[row<<2]=RAM[addr0+row*3];
- spb1[row<<2]=RAM[addr1+row*3];
- spb2[row<<2]=RAM[addr2+row*3]; }
- CopyBits((BitMap*)*spriteMapH,(BitMap*)(*(offScreenPtr->portPixMap)),&spr,&t,srcOr,nil); }
- SetPortPix (offScreenPtr->portPixMap);
- }
-
- /*
- void ScrollScreen()
- {
- word xscroll, yscroll;
-
- xscroll=VICRegister[0x16]&7; yscroll=(VICRegister[0x11]&7)-3;
- if (yscroll>0)
- BlockMove(lineStart[0],lineStart[yscroll],(320/8)*(200-yscroll));
- else if (yscroll<0)
- BlockMove(line
- */
- void DrawTextScreen(byte total)
- {
- word chr;
- byte row, col, line, pos;
- register word tempa, tempb;
- GrafPtr savePort;
- GDHandle saveDev;
- Rect back;
- short h;
- RGBColor backCol, frontCol;
-
- row=col=0;
- GetPort (&savePort);
- saveDev = GetGDevice();
- SetPort ((GrafPtr)offScreenPtr);
- SetGDevice (offDev);
- PenSize(1,1);
- /* SetOrigin(-(VICRegister[0x16]&7),-((VICRegister[0x11]&7)-3));*/
- if (VICRegister[0x11]&32) /* High Res mode */
- {
- VICCharDefs=RAM+VICAddrBase+((VICRegister[0x18]&8)?8192:0);
- for (chr=0;chr<1000;chr++) {
- FastDraw(row,col,chr);
- if (++col>39) {col=0;row++;} }
- }
- else if (total) {
- Index2Color (VICRegister[0x21], &backCol);
- RGBBackColor (&backCol);
- EraseRect (&screenRect);
- for (chr=0;chr<1000;chr++) {
- FastDraw(row,col,RAM[chr+VICScreenPage]);
- VICText[chr]=RAM[chr+VICScreenPage];
- if (++col>39) {col=0;row++;} } }
- else {
- Index2Color (VICRegister[0x21], &backCol);
- RGBBackColor (&backCol);
- for (chr=0;chr<1000;chr++) {
- if (VICText[chr]!=RAM[chr+VICScreenPage]) {
- SetRect (&back, (col<<3)+screenRect.left, (row<<3)+screenRect.top,
- (col<<3)+screenRect.left+8, (row<<3)+screenRect.top+8);
- EraseRect (&back);
- FastDraw(row,col,RAM[chr+VICScreenPage]);
- VICText[chr]=RAM[chr+VICScreenPage]; }
- if (++col>39) {col=0;row++;} } }
- /* SetOrigin(0,0);*/
- SetPort (savePort);
- SetGDevice (saveDev);
- /* ScrollRect(&fullRect, VICRegister[0x16]&7,(VICRegister[0x11]&7)-3,nil);*/
- }
-
- void DrawBorders()
- {
- GrafPtr savePort;
- GDHandle saveDev;
- RGBColor borderCol;
- Rect newLeft, newRight, newTop, newBottom;
-
- GetPort (&savePort);
- saveDev = GetGDevice();
- SetPort ((GrafPtr)offScreenPtr);
- SetGDevice (offDev);
- Index2Color (VICRegister[0x20], &borderCol);
- RGBBackColor (&borderCol);
- if (VICRegister[0x16]&8) {
- EraseRect(&leftRect);
- EraseRect(&rightRect);
- }
- else {
- newLeft = leftRect;
- OffsetRect (&newLeft, 4, 0);
- InsetRect (&newLeft, -4, 0);
- newRight = rightRect;
- OffsetRect (&newRight, -4, 0);
- InsetRect (&newRight, -4, 0);
- EraseRect(&newLeft);
- EraseRect(&newRight);
- }
- if (VICRegister[0x11]&8) {
- EraseRect(&botRect);
- EraseRect(&topRect);
- }
- else {
- newBottom = botRect;
- OffsetRect (&newBottom, 0, -2);
- InsetRect (&newBottom, 0, -2);
- newTop = topRect;
- OffsetRect (&newTop, 0, 2);
- InsetRect (&newTop, 0, -2);
- EraseRect(&newBottom);
- EraseRect(&newTop);
- }
- SetPort (savePort);
- SetGDevice (saveDev);
- }
-
- void CopyPortToScreen()
- {
- ForeColor (blackColor);
- BackColor (whiteColor);
- CopyBits ((BitMapPtr)*(offScreenPtr->portPixMap), &((GrafPtr)VICWind)->portBits, &fullRect, &fullRect, srcCopy, nil);
- }
-
- void BlankScreen()
- {
- GrafPtr savePort;
- GDHandle saveDev;
- RGBColor backCol;
-
- GetPort (&savePort);
- saveDev = GetGDevice();
- SetPort ((GrafPtr)offScreenPtr);
- SetGDevice (offDev);
- Index2Color (VICRegister[0x21], &backCol);
- RGBBackColor (&backCol);
- EraseRect (&fullRect);
- SetPort (savePort);
- SetGDevice (saveDev);
- CopyPortToScreen();
- return;
- }
-
- void RedrawVIC()
- {
- if (NotSameVIC()) { TotalRedrawVIC(); return; }
- VICAddrAdjust();
- SetPort((GrafPtr)VICWind);
- if (!VICRegister[0x11]&16) {
- BlankScreen();
- return;}
- DrawTextScreen(0);
- DrawBorders();
- if (VICRegister[0x15])
- DrawSprites();
- CopyPortToScreen();
- }
-
- void TotalRedrawVIC()
- {
- register byte addr;
-
- for (addr=0; addr<0x2f; addr++)
- VICRegister[addr]=RAM[0xd000+addr];
- VICAddrAdjust();
- SetPort((GrafPtr)VICWind);
- if (VICRegister[0x11]&16) /* screen blanking */
- ;
- else
- {
- BlankScreen();
- return;
- }
- DrawBorders();
- DrawTextScreen(1);
- if (VICRegister[0x15])
- DrawSprites();
- CopyPortToScreen();
- }
-
- void SetupColorTable (void)
- {
- VICTab = GetCTable (kClutID);
- HNoPurge ((Handle)VICTab);
- MoveHHi ((Handle)VICTab);
- }
-
- /*
- These next three are almost verbatim from the Tech Note "Principia Off Screen"
- */
-
- OSErr CreateGDevice (PixMapHandle basePixMap, GDHandle *retGDevice)
- {
- GDHandle newDevice;
- ITabHandle embryoITab;
- Rect deviceRect;
- OSErr error;
-
- error = noErr;
- newDevice = nil;
- embryoITab = nil;
-
- newDevice = (GDHandle)NewHandle(sizeof(GDevice));
- if (newDevice != nil)
- {
- embryoITab = (ITabHandle)NewHandleClear(2);
- if (embryoITab != nil)
- {
- deviceRect = (**basePixMap).bounds;
- (**newDevice).gdRefNum = 0;
- (**newDevice).gdID = 0;
- if ((**basePixMap).pixelSize <= 8)
- (**newDevice).gdType = clutType;
- else
- (**newDevice).gdType = directType;
- (**newDevice).gdITable = embryoITab;
- (**newDevice).gdResPref = 4;
- (**newDevice).gdSearchProc = nil;
- (**newDevice).gdCompProc = nil;
- (**newDevice).gdFlags = 0;
- (**newDevice).gdPMap = basePixMap;
- (**newDevice).gdRefCon = 0;
- (**newDevice).gdNextGD = nil;
- (**newDevice).gdRect = deviceRect;
- (**newDevice).gdMode = -1;
- (**newDevice).gdCCBytes = 0;
- (**newDevice).gdCCDepth = 0;
- (**newDevice).gdCCXData = 0;
- (**newDevice).gdCCXMask = 0;
- (**newDevice).gdReserved = 0;
- if ((**basePixMap).pixelSize > 1)
- SetDeviceAttribute( newDevice, gdDevType, true );
- SetDeviceAttribute( newDevice, noDriver, true );
- if ((**basePixMap).pixelSize <= 8)
- {
- MakeITable((**basePixMap).pmTable, (**newDevice).gdITable,(**newDevice).gdResPref);
- error = QDError();
- }
- }
- else
- error = MemError();
- }
- else
- error = MemError();
- if (error != noErr)
- {
- if (embryoITab != nil)
- DisposHandle( (Handle)embryoITab );
- if (newDevice != nil)
- DisposHandle( (Handle)newDevice );
- }
- else
- *retGDevice = newDevice;
- return error;
- }
-
- OSErr CreateOffScreen (Rect *bounds, short depth, CTabHandle colors, CGrafPtr *retPort, GDHandle *retGDevice)
- {
- CGrafPtr newPort;
- PixMapHandle newPixMap;
- GDHandle newDevice;
- long qdVersion;
- GrafPtr savedPort;
- SignedByte savedState;
- short bytesPerRow;
- OSErr error;
-
- newPort = nil;
- newPixMap = nil;
- newDevice = nil;
- error = noErr;
- if (colors != nil)
- {
- savedState = HGetState( (Handle)colors );
- HNoPurge( (Handle)colors );
- }
- bytesPerRow = ((depth * (bounds->right - bounds->left) + 31) >> 5) << 2;
- (void)Gestalt( gestaltQuickdrawVersion, &qdVersion );
- if (depth == 1 || depth == 2 || depth == 4 || depth == 8 ||
- ((depth == 16 || depth == 32) && qdVersion >= gestalt32BitQD))
- {
- if (bytesPerRow <= 0x3FFE)
- {
- if (depth <= 8)
- if (colors == nil)
- error = paramErr; /* no table for indexed depth */
- }
- else
- error = paramErr; /* too many bytes */
- }
- else
- error = paramErr; /* invalid depth */
- if (error == noErr)
- {
- newPort = (CGrafPtr)NewPtr( sizeof (CGrafPort) );
- if (newPort != nil)
- {
- GetPort (&savedPort);
- OpenCPort (newPort);
- newPort->portRect = *bounds;
- RectRgn (newPort->visRgn, bounds);
- ClipRect (bounds);
- error = SetUpPixMap (depth, bounds, colors, bytesPerRow, newPort->portPixMap);
- if (error == noErr)
- {
- newPixMap = newPort->portPixMap;
- error = CreateGDevice( newPixMap, &newDevice );
- }
- SetPort( savedPort );
- }
- else
- error = MemError();
- }
- if (colors != nil)
- HSetState( (Handle)colors, savedState );
- if (error != noErr)
- {
- if (newPixMap != nil)
- {
- DisposCTable( (**newPixMap).pmTable );
- DisposPtr( (**newPixMap).baseAddr );
- }
- if (newDevice != nil)
- {
- DisposHandle( (Handle)(**newDevice).gdITable );
- DisposHandle( (Handle)newDevice );
- }
- if (newPort != nil)
- {
- CloseCPort( newPort );
- DisposPtr( (Ptr)newPort );
- }
- }
- else
- {
- *retPort = newPort;
- *retGDevice = newDevice;
- }
- return error;
- }
-
- OSErr SetUpPixMap(short depth, Rect *bounds, CTabHandle colors, short bytesPerRow, PixMapHandle aPixMap)
- {
- CTabHandle newColors;
- Ptr offBaseAddr;
- OSErr error;
-
- error = noErr;
- newColors = nil;
- offBaseAddr = nil;
- if (depth <= 8)
- {
- newColors = colors;
- error = HandToHand( (Handle *)&newColors );
- }
- else
- {
- newColors = (CTabHandle)NewHandle(sizeof(ColorTable) - sizeof(CSpecArray));
- error = MemError();
- }
- if (error == noErr)
- {
- offBaseAddr = NewPtr((unsigned long)bytesPerRow * (bounds->bottom - bounds->top) );
- if (offBaseAddr != nil)
- {
- (**aPixMap).baseAddr = offBaseAddr;
- (**aPixMap).rowBytes = bytesPerRow | 0x8000;
- (**aPixMap).bounds = *bounds;
- (**aPixMap).pmVersion = 0;
- (**aPixMap).packType = 0;
- (**aPixMap).packSize = 0;
- (**aPixMap).hRes = kDefaultRes;
- (**aPixMap).vRes = kDefaultRes;
- (**aPixMap).pixelSize = depth;
- (**aPixMap).planeBytes = 0;
- (**aPixMap).pmReserved = 0;
- if (depth <= 8) /* PixMap is indexed */
- {
- (**aPixMap).pixelType = 0;
- (**aPixMap).cmpCount = 1;
- (**aPixMap).cmpSize = depth;
- (**aPixMap).pmTable = newColors;
- }
- else
- {
- (**aPixMap).pixelType = RGBDirect;
- (**aPixMap).cmpCount = 3;
- if (depth == 16)
- (**aPixMap).cmpSize = 5;
- else
- (**aPixMap).cmpSize = 8;
- (**newColors).ctSeed = 3 * (**aPixMap).cmpSize;
- (**newColors).ctFlags = 0;
- (**newColors).ctSize = 0;
- (**aPixMap).pmTable = newColors;
- }
- }
- else
- error = MemError();
- }
- else
- newColors = nil;
- if (error != noErr)
- {
- if (newColors != nil)
- DisposCTable(newColors);
- }
- return error;
- }
-
-